package com.pubinfo.passbook.engine.cell;

import com.pubinfo.passbook.common.exception.ServiceException;
import com.pubinfo.passbook.common.model.http.engine.ComputeParamSlot;
import com.pubinfo.passbook.engine.Computor;
import com.pubinfo.passbook.engine.cache.ComputeCache;
import com.pubinfo.passbook.engine.process.ParamenterProcessor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Collection;
import java.util.Collections;

/**
 * 计算单元
 *
 * @author zhouch
 */
@Slf4j
public abstract class ComputeUnit<T, R> implements Computor<T, R> {

    /**
     * 父计算链的缓存
     */
    @Setter
    protected ComputeCache cache;

    protected Collection<? extends ParamenterProcessor<T, R>> processors;

    /**
     * 获得该计算单元类型
     * {@link com.pubinfo.passbook.engine.constants.ComputeUnitType}
     *
     * @return
     */
    public abstract String getUnitType();

    /**
     * 获得计算单元名称 (中文)
     *
     * @return
     */
    public String getName() {
        return StringUtils.EMPTY;
    }

    /**
     * 参数插槽信息, 默认不需要参数
     *
     * @return
     */
    public Collection<ComputeParamSlot> getParamSlots() {
        return Collections.EMPTY_LIST;
    }

    /**
     * 装载参数处理器
     */
    public void loadProcessors(Collection<? extends ParamenterProcessor<?, ?>> processors) {
        this.processors = (Collection<? extends ParamenterProcessor<T, R>>) processors;
    }

    /**
     * 获得对应名称的参数值
     * （目前必须要让参数处理器的结果和计算单元的结果保持一致，暂时不设计计算单元复杂的参数类型系统了）
     *
     * @return
     */
    protected R getParamenter(T data, String placeholder) {
        for (ParamenterProcessor<T, R> processor : processors) {
            if (processor.getPlaceHolderName().contentEquals(placeholder)) {
                // 在执行时设置全局计算链的缓存
                processor.setCache(cache);
                log.info("参数处理器：{}, 占位符名称: {}", processor.getClass().getSimpleName(), placeholder);
                R value = processor.get(data);
                log.info("参数处理器: {}, 返回值: {}", processor.getClass().getSimpleName(), value);
                return value;
            }
        }

        throw new ServiceException("计算单元运行时：没有找到对应的参数加载器。");
    }

    /**
     * 将计算单元执行信息压入全局计算缓存中.
     */
    protected void outputComputeMessage(String name, String result) {
        if (StringUtils.isEmpty(name) || StringUtils.isEmpty(result)) {
            return;
        }

        String msg = name + ": " + result;
        cache.pushExecuteMessage(msg);
    }

    protected void outputComputeMessage(String result) {
        outputComputeMessage(getName(), result);
    }


}
